#pragma once
/*
 *	Copyright © 2008 University of Houston
 *	All rights reserved.
 */
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>

using namespace std;

class Trace
{
    static int    tracelevel;
public:
	
	enum Level{VERYDEBUG, DEBUG, INFO, WARNING, ERROR, CRITICAL, FATAL};
	
	static ostringstream oss;
	static int verbosity;
	
    static bool log(ostringstream& stringStream, Level level)
    {
	
		string levelName = Trace::levelName(level);
	
		// TODO: There is probably a prettier way to do this.
		if(level == VERYDEBUG)
		{
			if(Trace::verbosity >= 2)
				cout << levelName << ": " << stringStream.str() << endl;
		}
		else if(level == DEBUG)
		{
			if(Trace::verbosity >= 1)
				cout << levelName << ": " << stringStream.str() << endl;
		}
		else if( level <= Trace::WARNING )
			cout << levelName << ": " << stringStream.str() << endl;
		else
			cerr << levelName << ": " << stringStream.str() << endl;	
		
		oss.str("");
		
		return true;
    }

	static const char* levelName(Level level)
	{
		switch(level)
		{
			case VERYDEBUG:	return	"VDEBUG  ";
			case DEBUG: 	return 	"DEBUG   ";
			case INFO: 		return 	"INFO    ";
			case WARNING: 	return 	"WARNING ";
			case ERROR: 	return 	"ERROR   ";
			case CRITICAL:	return 	"CRITICAL";
			case FATAL: 	return 	"FATAL   ";
		}
		return "";
	}
};
#define LOG(text, level) \
{ostringstream oss; Trace::log((ostringstream&)(oss<<text), level);}
#define VDEBUG(text)			LOG(text, Trace::VERYDEBUG)
#define DEBUG(text)			LOG(text, Trace::DEBUG)
#define INFO(text)			LOG(text, Trace::INFO)
#define WARNING(text)		LOG(text, Trace::WARNING)
#define ERROR(text)			LOG(text, Trace::ERROR)
#define CRITICAL(text)		LOG(text, Trace::CRITICAL)
#define FATAL(text)			LOG(text, Trace::FATAL)
